# Virtual Router Simulator 
#
# Copyright (C) 2009-2010 VRSim Project
# Author: Choonho Son <choonho@kt.com>
# URL: <http://vrsim.googlecode.com>
# For license information, see LICENSE.TXT
#

import random
import VRSim.Globals as globals
from VRSim.Node.XML import XML
from VRSim.Utils import debug,  message

class Interface(XML):
    def __init__(self,  slot,  port,  type="Internal",  adapter="i82559er",  model="qemu",  enabled=False):
        XML.__init__(self, "interface")
        self.type = type
        self.type_list = ["Internal",  "Host", "User", "Bridge"]
        self.name = "Unknown"
        self.isEnabled = enabled      # physically equiped
        self.isAssigned = False     # logically connected
        self.model = model # model : {qemu | cisco }
        self.adapter = adapter
        #self.speed = self.updateSpeed()
        self.mac = self.generateMAC()
        self.slot = slot    # ex) 0, 1, ...
        self.port = port  #) ex) 0, 1, ...
        # Host Interface Specific
        self.HostIfName = "tap0"
        # Internal Interface Specific
        self.srcIP = "127.0.0.1"
        self.srcPort = None
        self.dstIP = "127.0.0.1"
        self.dstPort = None
        self.delay = 1
        # initialize
        self.updateName()
        
    def updateName(self):
        """ update interface name
        by slot number X port number X adapter
        """
        # find adapter
        if self.adapter == "rtl8139":
            # 10M, QEMU
            kindOfSlot = globals.qemu_ethernet_slot
        elif self.adapter == "i82559er":
            # 10/100M QEMU
            kindOfSlot = globals.qemu_fastethernet_slot
        elif self.adapter == "e1000":
            # 1G QEMU
            kindOfSlot = globals.qemu_gigaethernet_slot
        elif self.adapter == "C7200-IO-2FE" or self.adapter == "NM-1FE-TX":
            # 100M Cisco
            kindOfSlot = globals.cisco_fastethernet_slot
        elif self.adapter == "C7200-IO-GE-E":
            # 1G Cisco
            kindOfSlot = globals.cisco_gigaethernet_slot
        elif self.adapter == "PA-2FE-TX"  or self.adapter == "NM-16ESW":
            # 100M Cisco , 2FE
            kindOfSlot = globals.cisco_fastethernet_slot
        elif self.adapter == "PA-4E":
            # 10M Cisco, 4 port
            kindOfSlot = globals.cisco_ethernet_slot
        elif self.adapter == "PA-8E":
            # 10M Cisco, 8 port
            kindOfSlot = globals.cisco_ethernet_slot
        elif self.adapter == "PA-GE":
            # 1G Cisco
            kindOfSlot = globals.cisco_gigaethernet_slot
        else:
            # unknown port
            msg = "Cannot find interface name (adapter): " + str(self.adapter)
            debug(msg)
            kindOfSlot = globals.qemu_ethernet_slot
        
        # slots
        slotStr = "slot " + str(self.slot)
        slot_list = kindOfSlot[slotStr]
        try:
            self.name = slot_list[self.port]
        except:
            msg = "Undefined Interface name"
            debug(msg)
            self.name = "Unknown"
            
    def generateMAC(self):
        mac = "00:00:01"
        for i in range(3):
            value = random.randint(16, 255)
            strval = str( hex( value) )
            mac = mac + ":" + strval[2:4]
        
        return mac
        
    
    def getPossibleAdapter(self):
        """ return adapter LIST
        """
        if self.model == "cisco":
            # cisco model
            if self.slot == 0:
                return ["C7200-IO-2FE",  "C7200-IO-GE-E"]
            else:
                return ["PA-GE", "PA-2FE-TX",  "PA-4E",  "PA-8E"]
        # Cisco 3600 series
        elif self.model == "c3600":
            if self.slot == 0:
                return ["NM-1FE-TX"]
            else:
                return["NM-16ESW"]
        else:
            # QEMU model
            return ["rtl8139", "i82559er", "e1000"]        
            
    def changeAdapter(self,  aname):
        self.adapter = aname
        self.updateName()
        
    def setAssigned(self,  tf=True):
        """ tf: True/False
        """
        debug("call setAssigned")
        print self.slot,  self.port
        debug(tf)
        self.isAssigned = tf

    def setEnabled(self,  tf=True):
        """ tf: True/False
        """
        self.isEnabled = tf

    def setInternal(self,  srcPort,  dstPort,  delay=1):
        """ set Interface Internal
        Information
        """
        self.srcPort = srcPort
        self.dstPort = dstPort
        self.delay = delay
        
    def setClear(self):
        """ clear internal information
        self.isAssigned
        self.internal port information
        """
        self.isAssigned = False
        
    def getXML(self):
        debug("Called Interface::getXML")
        """ return Interface xml
        # internal connection
        <interface type='udp' slot='0' port='1'>        # slot and port is not in libvirt
           <source address='10001:127.0.0.1' port='10002'/>
           <model type='i82559er'/>
           <mac address='00:00:00:01:02:03'/>
        </interface>
        """
        interface = self.xml.createElement("interface")
        interface.setAttribute('slot',  str(self.slot) )
        interface.setAttribute('port',  str(self.port) )
        # No operation
        #if self.isAssigned == False:
        #    debug("Not Assigned")
        #    return interface
        
        source = self.xml.createElement("source")
        model = self.xml.createElement("model")
        model.setAttribute('type',  self.adapter)
        mac = self.xml.createElement("mac")
        mac.setAttribute('address',  self.mac)
        
        # Internal connection
        if self.type == "Internal" and self.isAssigned == True:
            debug("NIC: Internal Type")
            subtype = "udp"
            interface.setAttribute("type",  subtype)
            address = str(self.srcPort) + ":" + str(self.dstIP)
            port = str(self.dstPort)
            source.setAttribute('address',  address)
            source.setAttribute('port',  port)
        
            interface.appendChild(source)
            #interface.appendChild(target)
            interface.appendChild(model)
            interface.appendChild(mac)
        
        elif self.type == "Host":
            """
            <interface type='ethernet'>
                <target dev='vnet7'/>
                <script path='/etc/qemu-ifup-mynet'/>
            </interface>
            """
            debug("NIC: Host")
            subtype = "ethernet"
            interface.seetAttribute("type",  subtype)
            target = self.xml.createElement("target")
            target.setAttribute('dev', self.HostIfName)
            # Host connection
            interface.appendChild(target)
            interface.appendChild(model)
            interface.appendChild(mac)
            
        elif self.type == "Bridge":
            debug("NIC: Bridge type")
            subtype = "bridge"
            interface.setAttribute("type",  subtype)
            source.setAttribute('bridge', 'br0')
            target = self.xml.createElement("target")
            target.setAttribute('dev',  self.HostIfName)
            # Host connection
            interface.appendChild(source)
            interface.appendChild(target)
            interface.appendChild(model)
            interface.appendChild(mac)
        
        else:
            debug("NIC: default")
            subtype = "user"
            interface.setAttribute("type",  subtype)
            
        print "NIC type:" ,  self.type
        
        
        return interface
        
    def setXML(self,  interface):
        """
        slot, port are already assigned in devices
        # internal connection
        <interface type='udp' slot='0' port='1'>        # slot and port is not in libvirt
           <source address='10001:127.0.0.1' port='10002'/>
           <model type='i82559er'/>
           <mac address='00:00:00:01:02:03'/>
        </interface>
        self.name
        self.isEnabled
        self.isAssigned
        self.model = model # model : {qemu | cisco }
        self.adapter
        self.mac
        
        self.srcIP = "127.0.0.1"
        self.srcPort = None
        self.dstIP = "127.0.0.1"
        self.dstPort = None
        """
        self.isEnabled = True
        ptype = interface.getAttribute("type")
        node_source = interface.getElementsByTagName("source")
        node_model = interface.getElementsByTagName("model")
        node_mac = interface.getElementsByTagName("mac")
        
        debug("interface setXML")
        # Internal setting
        if ptype == "udp":
            self.type = "Internal" 
            if node_model:
                self.adapter = node_model[0].getAttribute("type")
                self.updateName()
                debug("updateName")
                debug(self.name)
                debug(self.adapter)
        
            if node_mac:
                self.mac = node_mac[0].getAttribute("address")
            if node_source:
                """ srcPort & dstPort is automatically reallocated
                    will be overrided
                """
                temp_addr = node_source[0].getAttribute("address")
                temp_str = temp_addr.split(":")
                self.srcPort = int(temp_str[0])
                self.dstIP = temp_str[1]
                dstPortStr = node_source[0].getAttribute("port")
                self.dstPort = int(dstPortStr)
                self.isAssigned = True
                debug("Port assigned")
                debug(self.srcPort,  "source port:")
                debug(self.dstPort,  "destination port:")
